package cn.com.bluemoon.daps.sync.controller;

import cn.com.bluemoon.common.KeyAnnotationClz;
import cn.com.bluemoon.common.UserPermission;
import cn.com.bluemoon.daps.common.datascope.BmPermission;
import cn.com.bluemoon.daps.common.domain.ResultBean;
import cn.com.bluemoon.daps.common.domain.UserInfoHolder;
import cn.com.bluemoon.daps.common.enums.SyncToEnv;
import cn.com.bluemoon.daps.sync.base.CompareResult;
import cn.com.bluemoon.daps.sync.base.SqlCompareResult;
import cn.com.bluemoon.daps.sync.service.DapModel2DevSyncService;
import cn.com.bluemoon.daps.sync.vo.model2dev.*;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author Jarod.Kong
 * @date 2021/6/16 16:57
 */
@Api(tags = "开发同步")
@RestController
@Slf4j
@Validated
@RequestMapping("/model2dev")
public class DapModel2DevSyncController {
    @Resource
    private DapModel2DevSyncService model2DevSyncService;

    @BmPermission(value = {"model:table:authorize"}, name = "同步情况列表数据", ignore = true)
    @PostMapping
    @ApiOperation(value = "开发同步-列表")
    @ApiResponses(value = {@ApiResponse(code = 500, message = "错误原因信息", response = Boolean.class), @ApiResponse(code = 200, message = "ok", responseContainer = "List", response = SyncTableInfoOut.class)})
    public ResultBean<IPage<SyncTableInfoOut>> syncList(@RequestBody @ApiParam(value = "开发同步列表查询条件") @Valid SyncTablePageVo searchVo) {
        IPage<SyncTableInfoOut> res = model2DevSyncService.querySyncList(searchVo);
        return ResultBean.page(res);
    }

    @BmPermission(value = {"model:table:authorize"}, name = "同步情况列表-查看同步记录", ignore = true)
    @PostMapping("/viewTask")
    @ApiOperation(value = "开发同步-列表-日志")
    @ApiResponses(value = {@ApiResponse(code = 500, message = "错误原因信息", response = Boolean.class), @ApiResponse(code = 200, message = "ok", responseContainer = "List", response = SyncTableTaskOut.class)})
    public ResultBean<IPage<SyncTableTaskOut>> viewSyncTasks(@Valid @RequestBody @ApiParam("开发同步列表-查看表日志入参") SyncTableTaskPageVo searchVo) {
        IPage<SyncTableTaskOut> res = model2DevSyncService.viewSyncTasks(searchVo);
        return ResultBean.page(res);
    }

    @BmPermission(value = {"model:table:authorize"}, name = "同步情况列表-查看同步记录-同步日志", ignore = true)
    @GetMapping("/viewTaskLog")
    @ApiOperation(value = "开发同步-列表-日志-开发/测试库日志-执行日志")
    @ApiResponses(value = {@ApiResponse(code = 500, message = "错误原因信息", response = Boolean.class), @ApiResponse(code = 200, message = "ok", response = String.class)})
    public ResultBean<String> viewSyncTaskLog(@RequestParam(value = "modelId") @ApiParam(value = "模型id") String modelId,
                                              @RequestParam(value = "syncTaskId") @ApiParam(value = "表同步任务id") String syncTaskId) {
        String log = model2DevSyncService.viewSyncTaskLog(syncTaskId);
        return ResultBean.ok(log);
    }

    @BmPermission(value = {"model:table:authorize"}, name = "同步开发库-进行库表与模型表对比")
    @PostMapping("/preSyncDev")
    @ApiOperation(value = "开发同步-同步开发库、开发同步-列表-同步开发库")
    @ApiResponses(value = {@ApiResponse(code = 500, message = "错误原因信息", response = Boolean.class), @ApiResponse(code = 200, message = "ok", responseContainer = "List", response = String.class)})
    @UserPermission.SingleRow(key = "modelId", keyFormClz = KeyAnnotationClz.RequestBody)
    public ResultBean<List<String>> preSyncDev(@Valid @RequestBody SyncRequestListVo requestListVo) {
        List<CompareResult<SqlCompareResult>> res = model2DevSyncService.syncPreCompareResult(requestListVo.getModelId(), SyncToEnv.DEV, requestListVo.getTableIds());
        return ResultBean.ok(res)
                .convert(function());
    }

    @BmPermission(value = {"model:table:authorize"}, name = "同步测试库-进行库表与模型表对比")
    @PostMapping("/preSyncTest")
    @ApiOperation(value = "开发同步-同步测试库、开发同步-列表-同步测试库")
    @ApiResponses(value = {@ApiResponse(code = 500, message = "错误原因信息", response = Boolean.class), @ApiResponse(code = 200, message = "ok", responseContainer = "List", response = String.class)})
    @UserPermission.SingleRow(key = "modelId", keyFormClz = KeyAnnotationClz.RequestBody)
    public ResultBean<List<String>> preSyncTest(@Valid @RequestBody SyncRequestListVo requestListVo) {
        List<CompareResult<SqlCompareResult>> res = model2DevSyncService.syncPreCompareResult(requestListVo.getModelId(), SyncToEnv.TEST, requestListVo.getTableIds());
        return ResultBean.ok(res)
                .convert(function());
    }

    /**
     * 转换
     * @return 结果
     */
    private Function<List<CompareResult<SqlCompareResult>>, List<String>> function() {
        return compareResults -> compareResults.stream()
                .map(CompareResult::getData).filter(Objects::nonNull)
                .map(SqlCompareResult::getScript).filter(Objects::nonNull)
                .flatMap(c -> c.getSqls().stream()).filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    @BmPermission(value = {"model:table:authorize"}, name = "同步开发库-进行库表与模型表对比且入库")
    @PostMapping("/syncDev")
    @ApiOperation(value = "开发同步-同步开发库-确定同步、开发同步-列表-同步开发库-确定同步")
    @ApiResponses(value = {@ApiResponse(code = 500, message = "错误原因信息", response = Boolean.class), @ApiResponse(code = 200, message = "ok", response = Boolean.class), @ApiResponse(code = 500, message = "错误", response = Boolean.class)})
    @UserPermission.SingleRow(key = "modelId", keyFormClz = KeyAnnotationClz.RequestBody)
    public ResultBean<Boolean> syncDev(@Valid @RequestBody SyncRequestListVo requestListVo) {
        boolean sync = model2DevSyncService.async(requestListVo.getModelId(), SyncToEnv.DEV, requestListVo.getTableIds(), UserInfoHolder.getUserInfoOrEmpty());
        return ResultBean.ok(sync);
    }

    @BmPermission(value = {"model:table:authorize"}, name = "同步测试库-进行库表与模型表对比且入库")
    @PostMapping("/syncTest")
    @ApiOperation(value = "开发同步-同步测试库-确定同步、开发同步-列表-同步测试库-确定同步")
    @ApiResponses(value = {@ApiResponse(code = 500, message = "错误原因信息", response = Boolean.class), @ApiResponse(code = 200, message = "ok", response = Boolean.class)})
    @UserPermission.SingleRow(key = "modelId", keyFormClz = KeyAnnotationClz.RequestBody)
    public ResultBean<Boolean> syncTest(@Valid @RequestBody SyncRequestListVo requestListVo) {
        boolean sync = model2DevSyncService.async(requestListVo.getModelId(), SyncToEnv.TEST, requestListVo.getTableIds(), UserInfoHolder.getUserInfoOrEmpty());
        return ResultBean.ok(sync);
    }

}
